package cn.kk.fluidcells.api;

import java.awt.Toolkit;
import java.util.EventObject;

public abstract class InputEvent extends EventObject {

    private final long timeEvent;

    private int modifiers;

    public static final int MASK_SHIFT = 1;

    public static final int MASK_CTRL = 1 << 1;

    public static final int MASK_META = 1 << 2;

    public static final int MASK_ALT = 1 << 3;

    public static final int MASK_FN = 1 << 4;

    public static final int MASK_LBUTTON = 1 << 5;

    public static final int MASK_RBUTTON = 1 << 6;

    public static final int MASK_MBUTTON = 1 << 7;

    public static final int MASK_XBUTTON1 = 1 << 8;

    public static final int MASK_XBUTTON2 = 1 << 9;

    public InputEvent(final Object src, final long evtTime, final int modifiers) {
        super(src);

        this.timeEvent = evtTime;
        this.modifiers = modifiers;
    }

    /**
     * Gets the modifier flags for this event.
     * 
     * @return the modifier flags
     */
    public int getModifiers() {
        return this.modifiers;
    }

    /**
     * Sets the modifier flags for this event.
     * 
     * @param modifiers
     *            the new modifier flags
     */
    public void setModifiers(int modifiers) {
        this.modifiers = modifiers;
    }

    /**
     * Gets a <code>String</code> describing the modifier flags, such as "Button1", or "Ctrl+Alt". These strings can be
     * localized by changing the awt.properties file.
     * 
     * @param modifiers
     *            a modifier mask describing the modifier keys and mouse buttons of an event.
     * @return the modifier mask's textual representation
     */
    public static final String getModifiersText(int modifiers) {
        StringBuilder param = new StringBuilder(128);

        if ((modifiers & InputEvent.MASK_FN) != 0) {
            param.append("Fn");
            param.append('+');
        }

        if ((modifiers & InputEvent.MASK_SHIFT) != 0) {
            param.append(Toolkit.getProperty("AWT.shift", "Shift"));
            param.append('+');
        }

        if ((modifiers & InputEvent.MASK_CTRL) != 0) {
            param.append(Toolkit.getProperty("AWT.control", "Ctrl"));
            param.append('+');
        }

        if ((modifiers & InputEvent.MASK_META) != 0) {
            param.append(Toolkit.getProperty("AWT.meta", "Meta"));
            param.append('+');
        }

        if ((modifiers & InputEvent.MASK_ALT) != 0) {
            param.append(Toolkit.getProperty("AWT.alt", "Alt"));
            param.append('+');
        }

        if ((modifiers & InputEvent.MASK_LBUTTON) != 0) {
            param.append(Toolkit.getProperty("AWT.button1", "Left-Button"));
            param.append('+');
        }

        if ((modifiers & InputEvent.MASK_RBUTTON) != 0) {
            param.append(Toolkit.getProperty("AWT.button2", "Right-Button"));
            param.append('+');
        }

        if ((modifiers & InputEvent.MASK_MBUTTON) != 0) {
            param.append(Toolkit.getProperty("AWT.button3", "Middle-Button"));
            param.append('+');
        }

        if ((modifiers & InputEvent.MASK_XBUTTON1) != 0) {
            param.append(Toolkit.getProperty("AWT.button4", "XButton-1"));
            param.append('+');
        }

        if ((modifiers & InputEvent.MASK_XBUTTON2) != 0) {
            param.append(Toolkit.getProperty("AWT.button5", "XButton-2"));
            param.append('+');
        }

        if (param.length() > 0) {
            param.deleteCharAt(param.length() - 1);
        }

        return param.toString();
    }

    @Override
    public String toString() {
        StringBuilder param = new StringBuilder(255);

        param.append("occurred=");
        param.append(getTimeOccurred());
        param.append(", ");

        param.append("mask=");
        param.append(Integer.toBinaryString(getModifiers()));
        param.append(", ");

        param.append("modifiers=");
        param.append(InputEvent.getModifiersText(getModifiers()));

        return param.toString();
    }

    private Object getTimeOccurred() {
        return this.timeEvent;
    }
}
